import { MiddlewareConsumer, Module, NestModule, ValidationError, ValidationPipe } from '@nestjs/common';
import { AdminModule } from './main/admin.module';
import { CommonModule } from './common/common.module';
import { AuthMiddleware } from './common/middleware/auth/auth.middleware';
import { AuthService } from './common/service/auth/auth.service';
import { Config } from './config';
import { PermissionGuard } from './common/guard/permission/permission.guard';
import { RoleGuard } from './common/guard/permission/role.guard';
import { APP_FILTER, APP_GUARD, APP_INTERCEPTOR, APP_PIPE } from '@nestjs/core';
import {
  AssertionErrorFilter,
  AuthorizationFilter,
  BadRequestFilter,
  ForbiddenExceptionFilter,
  GlobalErrorFilter,
  MulterErrFilter,
  NotFoundErrFilter,
  PayloadTooLargeFilter,
  ThrottlerExceptionFilter,
  ValidationExceptionFilter
} from '@admin/common/filter/global-error.filter';
import { ValidationException } from './common/exception/ValidationException';
import { ThrottlerModule } from '@nestjs/throttler';
import { ThrottlerCustomGuard } from './common/guard/throttler/throttler-custom.guard';
import { RemoveThrottleHeadersInterceptor } from './common/interceptors/remove-throttle-headers.interceptor';
import '@admin/common/utils/email';
import { ScheduleModule } from '@nestjs/schedule';
import { TasksService } from './schedule';
import { ThrottlerStorageRedisService } from 'nestjs-throttler-storage-redis';
import { WebModule } from './web/web.module';
import { ConfigModule } from '@nestjs/config';
@Module({
  imports: [
    AdminModule,
    CommonModule,
    ThrottlerModule.forRoot({
      throttlers: [
        {
          name: 'default',
          ttl: Config.rateLimit.ttl,
          limit: Config.rateLimit.limit
        }
      ],
      storage:
        Config.rateLimit.storage === 'redis'
          ? new ThrottlerStorageRedisService({
              ...Config.redis,
              disconnectTimeout: 60 * 5 * 1000
            })
          : null
    }),
    ScheduleModule.forRoot(),
    WebModule,
    ConfigModule.forRoot({
      // envFilePath: ['.env.local']
      envFilePath: ['./.env.development']
    })
  ],
  controllers: [],
  providers: [
    TasksService,
    AuthService,
    PermissionGuard,
    RoleGuard,
    {
      provide: APP_GUARD,
      useClass: ThrottlerCustomGuard
    },
    {
      provide: APP_GUARD,
      useClass: PermissionGuard
    },
    {
      provide: APP_GUARD,
      useClass: RoleGuard
    },
    {
      provide: APP_FILTER,
      useClass: GlobalErrorFilter
    },
    {
      provide: APP_FILTER,
      useClass: BadRequestFilter
    },
    {
      provide: APP_FILTER,
      useClass: ThrottlerExceptionFilter
    },
    {
      provide: APP_FILTER,
      useClass: PayloadTooLargeFilter
    },
    {
      provide: APP_FILTER,
      useClass: AuthorizationFilter
    },
    {
      provide: APP_FILTER,
      useClass: ForbiddenExceptionFilter
    },
    {
      provide: APP_FILTER,
      useClass: AssertionErrorFilter
    },
    {
      provide: APP_FILTER,
      useClass: ValidationExceptionFilter
    },
    {
      provide: APP_FILTER,
      useClass: MulterErrFilter
    },
    {
      provide: APP_FILTER,
      useClass: NotFoundErrFilter
    },
    {
      provide: APP_PIPE,
      useFactory() {
        return new ValidationPipe({
          whitelist: true, // 自动剔除非 DTO 类中的字段
          // forbidNonWhitelisted: true, // 如果存在非 DTO 类中的字段则抛出异常
          exceptionFactory: (errors: ValidationError[]) => {
            const messages = errors.map(error => Object.values(error.constraints)).flat();
            return new ValidationException(`参数验证失败: ${messages[0]}`);
            // return new ValidationException(`参数验证失败: ${messages.join(', ')}`);
          }
        });
      }
    },
    {
      provide: APP_INTERCEPTOR,
      useClass: RemoveThrottleHeadersInterceptor
    }
  ]
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer.apply(AuthMiddleware).exclude('/login', '/logout', '/captchaImage').forRoutes('*');
  }
}
